package cn.zwx.common.elastic.config;

import org.apache.http.HttpHost;
import org.apache.http.auth.AuthScope;
import org.apache.http.auth.UsernamePasswordCredentials;
import org.apache.http.client.CredentialsProvider;
import org.apache.http.impl.client.BasicCredentialsProvider;
import org.apache.http.impl.nio.client.HttpAsyncClientBuilder;
import org.elasticsearch.client.Node;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestClientBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.elasticsearch.config.ElasticsearchConfigurationSupport;
import org.springframework.util.ObjectUtils;


/**
 * @author zhangwenxue
 */
@Configuration
@EnableConfigurationProperties(ElasticProperty.class)
public class ElasticSearchConfig extends ElasticsearchConfigurationSupport {

    public static final Logger logger = LoggerFactory.getLogger(ElasticSearchConfig.class);


    private static final String HTTP_STR = "http://";
    private static final String HTTPS_STR = "https://";
    private static final String COLON_STR = ":";

    private final ElasticProperty elasticProperty;

    public ElasticSearchConfig(ElasticProperty property) {
        this.elasticProperty = property;
    }


    @Bean
    public RestClientBuilder restClientBuilder() {
        return RestClient.builder(elasticProperty.getUris().stream().map(this::getElasticSearchHttpHosts).toArray(HttpHost[]::new)).
                setRequestConfigCallback(requestConfigBuilder -> {
                    //设置连接超时时间
                    requestConfigBuilder.setConnectTimeout(elasticProperty.getConnectTimeOut());
                    requestConfigBuilder.setSocketTimeout(elasticProperty.getSocketTimeOut());
                    requestConfigBuilder.setConnectionRequestTimeout(elasticProperty.getConnectionRequestTimeOut());
                    return requestConfigBuilder;
                }).setFailureListener(new RestClient.FailureListener() {
                    //某节点失败,这里可以做一些告警
                    @Override
                    public void onFailure(Node node) {
                        logger.error("[ ElasticSearchClient ] >>  node :{}, host:{},  fail ", node.getName(), node.getHost());
                    }
                }).setHttpClientConfigCallback(httpClientBuilder -> {
                    httpClientBuilder.setMaxConnTotal(elasticProperty.getMaxConnectNum());
                    httpClientBuilder.setMaxConnPerRoute(elasticProperty.getMaxConnectPerRoute());
                    //设置账密
                    return getHttpAsyncClientBuilder(httpClientBuilder);
                });
    }


    private HttpHost getElasticSearchHttpHosts(String host) {
        host = host.replaceAll(HTTP_STR, "").replaceAll(HTTPS_STR, "");
        return new HttpHost(host.split(COLON_STR)[0], Integer.parseInt(host.split(COLON_STR)[1]), "http");
    }

    private HttpAsyncClientBuilder getHttpAsyncClientBuilder(HttpAsyncClientBuilder httpClientBuilder) {
        if (ObjectUtils.isEmpty(elasticProperty.getUsername()) || ObjectUtils.isEmpty(elasticProperty.getPassword())) {
            return httpClientBuilder;
        }
        //设置账号密码
        CredentialsProvider credentialsProvider = new BasicCredentialsProvider();
        credentialsProvider.setCredentials(AuthScope.ANY, new UsernamePasswordCredentials(elasticProperty.getUsername(), elasticProperty.getPassword()));
        httpClientBuilder.setDefaultCredentialsProvider(credentialsProvider);
        return httpClientBuilder;
    }
}
